/**
 * 
 */
package pers.vic.test.http;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;


/**
 *  @description: 替换request ,保证request的body可重复读的过滤器
 *  @author Vic.xu
 *  @date: 2020年5月20日上午9:07:14
 */
public class ReplaceHttpRequest4RepeatReadBodyFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 是否拦截
		if(!judgeFilter(request)) {
			 chain.doFilter(request, response);
			 return;
		}
		
		// 重新包装流, 只包装JSON请求的
		ServletRequest requestWrapper = null;
        if(request instanceof HttpServletRequest && isJsonRequest(request)) {
            requestWrapper = new RepeatReadServletRequestBodyWrapper((HttpServletRequest) request);
        }
        //获取请求中的流如何，将取出来的字符串，再次转换成流，然后把它放入到新request对象中。
        if(requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
	}

	private static final String FILTER_PREFIX = "";
	
	/**
	 * 只拦截指定前缀的url
	 * @param request
	 * @return
	 */
	private boolean judgeFilter(ServletRequest request) {
		String url = getRequestUrl((HttpServletRequest) request);
		return url.startsWith(FILTER_PREFIX);
	}
	
	/** 
	 * 获得当前请求的URL
	 * 不是用request.getServletPath() 是因为这个API和URL-MAPPING有变化关系
	 */
	public static String getRequestUrl(HttpServletRequest request) {
		String contextPath = request.getContextPath();
		String requestURI = request.getRequestURI();
		int i = requestURI.indexOf("?");
		if (i < 0) {
			i = requestURI.length();
		}
		return requestURI.substring(contextPath.length(), i);
	}
	
	/**
	 * 是否是JSON请求格式
	 * @param request
	 * @return
	 */
	public static boolean isJsonRequest(ServletRequest request) {
		String enctype = request.getContentType();  
		return StringUtils.isNotBlank(enctype) && enctype.contains(MediaType.APPLICATION_JSON_VALUE);
	}


}
